import java.util.List;


public class Heuristics1{
	static int scoring1(NewState1 state){
		// Returns an integer, whereas the more minus the worse, the more plus the better.
		int enemyFleet = 0;
		int enemyGrowth = 0;
		int friendlyFleet = 0;
		int friendlyGrowth = 0;

		//*Eliminating double for loop make one instead
		for(Planet planet : state.Planets()){
			switch (planet.Owner()) {
			case NewState1.NEUTRAL:

				break;
			case NewState1.FRIENDLY:
				friendlyFleet += planet.NumShips();
				friendlyGrowth += planet.GrowthRate();
				break;

			default:
				enemyFleet += planet.NumShips();
				enemyGrowth += planet.GrowthRate();
				break;
			}
		}
		//		for (Planet ePlanet : state.EnemyPlanets())
		//		{
		//			enemyFleet += ePlanet.NumShips();
		//			enemyGrowth += ePlanet.GrowthRate();
		//		}
		double enemyInfo = enemyFleet + enemyGrowth * 4; 

		//		for (Planet fPlanet : state.MyPlanets())
		//		{
		//			friendlyFleet += fPlanet.NumShips();
		//			friendlyGrowth += fPlanet.GrowthRate();
		//		}
		double friendlyInfo = friendlyFleet + friendlyGrowth * 4;

		//System.err.println("Friendly: " + friendlyInfo +", Enemy: " + enemyInfo);
		if (enemyInfo == 0)
		{
			return Integer.MAX_VALUE;
		} 
		else if (friendlyInfo == 0)
		{
			return Integer.MIN_VALUE;
		}
		else
		{
			return (int)(friendlyInfo - enemyInfo);
		}
	}
	
	public static NewState1 InitialState = null;
	
	static int scoringUsingStateDepth(NewState1 state){
		// Calculate stateDepth
		int stateDepth = 1;
		NewState1 tempState = state;
		if (InitialState != null)
		{
			while (tempState.getParent() != InitialState)
			{
				tempState = tempState.getParent();
				stateDepth++;
			}
		}
		
		// Returns an integer, whereas the more minus the worse, the more plus the better.
		int enemyFleet = 0;
		int enemyGrowth = 0;
		int friendlyFleet = 0;
		int friendlyGrowth = 0;

		//*Eliminating double for loop make one instead
		for(Planet planet : state.Planets()){
			switch (planet.Owner()) {
			case NewState1.NEUTRAL:

				break;
			case NewState1.FRIENDLY:
				friendlyFleet += planet.NumShips();
				friendlyGrowth += planet.GrowthRate();
				break;

			default:
				enemyFleet += planet.NumShips();
				enemyGrowth += planet.GrowthRate();
				break;
			}
		}
		//		for (Planet ePlanet : state.EnemyPlanets())
		//		{
		//			enemyFleet += ePlanet.NumShips();
		//			enemyGrowth += ePlanet.GrowthRate();
		//		}
		double enemyInfo = enemyFleet + enemyGrowth * 4; 

		//		for (Planet fPlanet : state.MyPlanets())
		//		{
		//			friendlyFleet += fPlanet.NumShips();
		//			friendlyGrowth += fPlanet.GrowthRate();
		//		}
		double friendlyInfo = friendlyFleet + friendlyGrowth * 4;

		if (enemyInfo == 0)
		{
			return (int)(Integer.MAX_VALUE / stateDepth);
		} 
		else if (friendlyInfo == 0)
		{
			return (int)(Integer.MIN_VALUE / stateDepth);
		}
		else
		{
			return (int)((friendlyInfo - enemyInfo) / stateDepth);
		}
	}
	
	static double enemyFleetRelevance = 1;
	static double enemyGrowthRelevance = 3;
	static double friendlyFleetRelevance = 1;
	static double friendlyGrowthRelevance = 3;
	
	static int enemyHeuristic(NewState1 state)
	{
		int enemyFleet = 0;
		int enemyGrowth = 0;
		int friendlyFleet = 0;
		int friendlyGrowth = 0;

		for(Planet planet : state.Planets()){
			switch (planet.Owner()) {
			case NewState1.NEUTRAL:

				break;
			case NewState1.FRIENDLY:
				friendlyFleet += planet.NumShips();
				friendlyGrowth += planet.GrowthRate();
				break;

			default:
				enemyFleet += planet.NumShips();
				enemyGrowth += planet.GrowthRate();
				break;
			}
		}
		
		double enemyInfo = enemyFleet * enemyFleetRelevance + enemyGrowth * enemyGrowthRelevance; 

		double friendlyInfo = friendlyFleet * friendlyFleetRelevance + friendlyGrowth * friendlyGrowthRelevance;

		if (enemyInfo == 0)
		{
			return Integer.MAX_VALUE;
		} 
		else if (friendlyInfo == 0)
		{
			return Integer.MIN_VALUE;
		}
		else
		{
			return (int)(friendlyInfo - enemyInfo);
		}
	}
	
	static void adaptEnemyHeuristic(List<NewState1> possibleStates, NewState1 action)
	{
		int topHeuristic = Integer.MAX_VALUE;
		NewState1 topState = action;
		for (NewState1 state : possibleStates)
		{
			int heur = enemyHeuristic(state);
			if (heur < topHeuristic)
			{
				topHeuristic = heur;
				topState = state;
			}
		}
		if (topState == action)
			return;

		int actionEnemyFleet = 0;
		int actionEnemyGrowth = 0;
		int actionFriendlyFleet = 0;
		int actionFriendlyGrowth = 0;

		for(Planet planet : action.Planets()){
			switch (planet.Owner()) {
			case NewState1.NEUTRAL:
 
				break;
			case NewState1.FRIENDLY:
				actionFriendlyFleet += planet.NumShips();
				actionFriendlyGrowth += planet.GrowthRate();
				break;

			default:
				actionEnemyFleet += planet.NumShips();
				actionEnemyGrowth += planet.GrowthRate();
				break;
			}
		}

		double actionEnemyInfo = actionEnemyFleet * enemyFleetRelevance + actionEnemyGrowth * enemyGrowthRelevance; 
		double actionFriendlyInfo = actionFriendlyFleet * friendlyFleetRelevance + actionFriendlyGrowth * friendlyGrowthRelevance;
		
		int topStateEnemyFleet = 0;
		int topStateEnemyGrowth = 0;
		int topStateFriendlyFleet = 0;
		int topStateFriendlyGrowth = 0;

		for(Planet planet : topState.Planets()){
			switch (planet.Owner()) {
			case NewState1.NEUTRAL:

				break;
			case NewState1.FRIENDLY:
				topStateFriendlyFleet += planet.NumShips();
				topStateFriendlyGrowth += planet.GrowthRate();
				break;

			default:
				topStateEnemyFleet += planet.NumShips();
				topStateEnemyGrowth += planet.GrowthRate();
				break;
			}
		}
		double topStateEnemyInfo = topStateEnemyFleet * enemyFleetRelevance + topStateEnemyGrowth * enemyGrowthRelevance; 
		double topStateFriendlyInfo = topStateFriendlyFleet * friendlyFleetRelevance + topStateFriendlyGrowth * friendlyGrowthRelevance;
		
		double friendlyFleetNr = actionFriendlyFleet / topStateFriendlyFleet;
		double enemyFleetNr = actionEnemyFleet / topStateEnemyFleet;
		double friendlyGrowthNr = actionFriendlyGrowth / topStateFriendlyGrowth;
		double enemyGrowthNr = actionEnemyGrowth / topStateEnemyGrowth;
		
		double friendlyNr = actionFriendlyInfo / topStateFriendlyInfo;
		double enemyNr = actionEnemyInfo / topStateEnemyInfo;
		
		friendlyFleetNr /= friendlyNr;
		friendlyGrowthNr /= friendlyNr;
		enemyFleetNr /= enemyNr;
		enemyGrowthNr /= enemyNr;
		
		enemyFleetRelevance *= enemyFleetNr;
		enemyGrowthRelevance *= enemyGrowthNr;
		friendlyFleetRelevance *= friendlyFleetNr;
		friendlyGrowthRelevance *= friendlyGrowthNr;
	}
}